package com.itheima.app.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.FocusUser;
import com.itheima.domain.mongo.Video;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.FocusUserService;
import com.itheima.service.mongo.VideoService;
import com.itheima.util.ConstantUtil;
import com.itheima.vo.CommentVo;
import com.itheima.vo.PageBeanVo;
import com.itheima.vo.VideoVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class VideoManager {

    @DubboReference
    VideoService videoService;

    @DubboReference
    UserInfoService userInfoService;

    @Autowired
    FastFileStorageClient client;

    @Autowired
    FdfsWebServer server;

    @DubboReference
    FocusUserService focusUserService;

    @DubboReference
    CommentService commentService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    MQVideoManager mqVideoManager;

    //推荐视频列表
    @Cacheable(value = "tanhua_video", key = "#userId+'_'+#pageNum+'_'+#pageSize")// 99_1_10
    public PageBeanVo findRecommendVideoByPage(Long userId, Integer pageNum, Integer pageSize) {
        System.out.println("------------------------------------");

        //2.远程调用service查询pageBeanVo
        PageBeanVo pageBeanVo = videoService.findRecommendVideoByPage(userId, pageNum, pageSize);

        //3.获取分页对象中的视频集合,遍历,获取每个视频对象,获取视频发布者userInfo,将video和userInfo封装videoVO对象,将vo对象放入vo集合中
        List<Video> items = (List<Video>) pageBeanVo.getItems();

        List<VideoVo> voList = new ArrayList<>();

        if (CollUtil.isNotEmpty(items)) {
            items.forEach(v -> {
                // 获取视频发布者userInfo,
                UserInfo userInfo = userInfoService.findByUserId(v.getUserId());

                // 将video和userInfo封装videoVO对象,
                VideoVo vo = new VideoVo();
                // 先封装userInfo再封装视频
                vo.setUserInfo(userInfo);
                vo.setVideo(v);

                //判断是否关注用户
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.FOCUS_USER, userId, v.getUserId()))) {
                    vo.setHasFocus(1);
                }

                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.VIDEO_LIKE, userId, v.getId().toString()))) {
                    vo.setHasLiked(1);
                }

                // 将vo对象放入vo集合
                voList.add(vo);
            });
        }

        //4.将vo集合设置给pageBeanVo
        pageBeanVo.setItems(voList);
        //5.返回pageBeanVo
        return pageBeanVo;
    }

    //@CacheEvict(value = "tanhua",allEntries = true)
    @CacheEvict(value = "tanhua_video", key = "#userId+'_*'")
    public void save(Long userId, MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        //1.将封面和视频上传到FastDFS上,获取路径
        StorePath coverPath = client.uploadFile(videoThumbnail.getInputStream(), videoThumbnail.getSize(), FileUtil.extName(videoThumbnail.getOriginalFilename()), null);
        StorePath videoPath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), FileUtil.extName(videoFile.getOriginalFilename()), null);

        //2.创建video对象,封装video
        Video video = new Video();

        video.setCreated(System.currentTimeMillis());
        video.setUserId(userId);
        video.setPicUrl(server.getWebServerUrl() + coverPath.getFullPath());
        video.setVideoUrl(server.getWebServerUrl() + videoPath.getFullPath());

        System.out.println(video.getVideoUrl());
        System.out.println(video.getPicUrl());

        //3.远程调用service完成保存操作
        videoService.save(video);

        //给mq发送消息
        mqVideoManager.sendVideo(userId, video.getId(), MQVideoManager.VIDEO_PUBLISH);

    }

    public void focusUser(Long focusUserId) {
        //1.获取当前登陆者id
        Long userId = UserHolder.get().getId();

        //2.创建FocusUser对象且封装
        FocusUser focusUser = new FocusUser();
        focusUser.setCreated(System.currentTimeMillis());
        focusUser.setUserId(userId);
        focusUser.setFocusUserId(focusUserId);

        //3.远程调用service完成操作
        focusUserService.save(focusUser);

        //4.添加关注的标记(redis)  //  focus_user:用户id_被关注的用户id
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.FOCUS_USER, userId, focusUserId), "1");
    }

    public void unFocusUser(Long focusUserId) {
        //1.获取当前登陆者id
        Long userId = UserHolder.get().getId();

        //2.远程调用service完成删除操作
        focusUserService.delete(userId, focusUserId);

        //3.删除关注的标记(redis)
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.FOCUS_USER, userId, focusUserId));
    }


    //    视频点赞功能
    @CacheEvict(value = "tanhua_video", key = "#userId+'_*'")
    public ResponseEntity videosLike(Long userId, String publishId) {

        //根据publishId查询视频信息
        Video video = videoService.findById(new ObjectId(publishId));
        //根据视频信息封装Comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(4);
        comment.setUserId(userId);
        comment.setPublishUserId(video.getUserId());

        //4.远程调用videoService进行保存
        int count = commentService.save(comment);


        //5.标记当前用户对这条动态点过赞(redis)
        //  key : video_like:用户id_动态id
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.VIDEO_LIKE, userId, publishId), "4");
        // value: 值都是1

        //给mq发送消息
        mqVideoManager.sendVideo(userId, video.getId(), MQVideoManager.VIDEO_LIKE);

        //6.返回最新的操作数量
        return ResponseEntity.ok(count);

    }

    //取消点赞功能
    @CacheEvict(value = "tanhua_video", key = "#userId+'_*'")
    public ResponseEntity videosDislike(Long userId, String publishId) {

        int count = commentService.delete(userId, new ObjectId(publishId), 4);

        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.VIDEO_LIKE, userId, publishId));

        //给mq发送消息
        mqVideoManager.sendVideo(userId, new ObjectId(publishId), MQVideoManager.VIDEO_DISLIKE);
        return ResponseEntity.ok(count);
    }


    //    发布视频评论
    @CacheEvict(value = "tanhua_video", key = "'video_comment_' + #userId + '_*'")
    public ResponseEntity videosComment(String publishId, String content, Long userId) {

        //1.远程调用movementService查询动态对象
        Video video = videoService.findById(new ObjectId(publishId));

        //2.封装Comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(new ObjectId(publishId));
        comment.setContent(content);
        comment.setCommentType(5); //评论  : 5
        comment.setUserId(userId);
        comment.setPublishUserId(video.getUserId());

        //3.远程调用service进行保存
        int count = commentService.save(comment);

        //将 对动态的行为 发送mq中
//        mqMovementManager.sendMovement(video.getUserId(),video.getId(),MQMovementManager.MOVEMENT_COMMENT);

        return ResponseEntity.ok(count);
    }


    /**
     * 分页查询视频评论列表
     *
     * @param publishId
     * @param pageNum
     * @param pageSize
     * @param userId
     * @return
     */
    @Cacheable(value = "tanhua_video", key = "'video_comment_' + #userId+'_'+#publishId +'_'+#pageNum+'_'+#pageSize")
    public PageBeanVo findVideoCommentsByPage(String publishId, Integer pageNum, Integer pageSize, Long userId) {
        //调用远程service查询数据
        PageBeanVo pageBeanVo = videoService.findVideoCommentsByPage(new ObjectId(publishId), pageNum, pageSize);

        //查询用户信息,重新封装vo集合
        List<Comment> items = (List<Comment>) pageBeanVo.getItems();
        List<CommentVo> vos = new ArrayList<>();

        if (CollectionUtil.isNotEmpty(items)) {
            items.forEach(e -> {
                CommentVo vo = new CommentVo();
                UserInfo userInfo = userInfoService.findByUserId(e.getUserId());
                vo.setNickname(userInfo.getNickname());
                vo.setAvatar(userInfo.getAvatar());
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.VIDEO_COMMENT_LIKE, UserHolder.get().getId(), e.getId()))) {
                    vo.setHasLiked(1);
                }
                vo.setCreateDate(DateUtil.formatDateTime(new Date(e.getCreated())));
                vo.setContent(e.getContent());
                vo.setId(e.getId().toString());
                vo.setLikeCount(e.getLikeCount());

                vos.add(vo);
            });
        }

        //重新封装pageBeanVo,并返回数据
        pageBeanVo.setItems(vos);

        return pageBeanVo;

    }

    /**
     * 评论点赞
     *
     * @param commentId
     * @param userId
     * @return
     */
    @CacheEvict(value = "tanhua_video", key = "'video_comment_' + #userId + '_*'")
    public ResponseEntity videoCommentLike(String commentId, Long userId) {
        //获取视频信息
        Comment targetComment = commentService.findById(new ObjectId(commentId));
        //封装comment
        Comment comment = new Comment();
        comment.setCommentType(6);
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(userId);
        comment.setPublishUserId(targetComment.getUserId());
        comment.setPublishId(new ObjectId(commentId));
        //调用远程service进行评论插入
        commentService.save(comment);

        //给redis插入标记
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.VIDEO_COMMENT_LIKE, userId, commentId), "1");

        //返回
        return ResponseEntity.ok(null);

    }
}
